package homegroup.inc.servlets;

import homegroup.inc.dao.BookDAO;
import homegroup.inc.dto.Book;
import homegroup.inc.exceptions.IllegalBookCoverFileExtension;
import homegroup.inc.exceptions.IllegalBookFileExtension;
import homegroup.inc.exceptions.IllegalImageResolution;
import homegroup.inc.utils.BookParameters;

import javax.ejb.EJB;
import javax.persistence.RollbackException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by stone on 23.11.2014.
 */
@WebServlet(name = "UploadServlet", urlPatterns = {"/upload"})
@MultipartConfig
public class UploadServlet extends HttpServlet {

    @EJB
    BookDAO bookDAO;

    private Book book;
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        PrintWriter writer = response.getWriter();

        Map<String, String[]> formParams = request.getParameterMap();
        Map<String, String> pathFiles;
        try {
            pathFiles = process(request);
            book = new Book();
            book.setAuthor(formParams.get("author")[0]);
            book.setISBN(formParams.get("isbn")[0]);
            book.setDescription(formParams.get("description")[0]);
            book.setPublisher(formParams.get("publisher")[0]);
            book.setTitle(formParams.get("title")[0]);
            book.setBookPath(pathFiles.get("bookFile"));
            book.setCoverPath(pathFiles.get("coverFile"));
            bookDAO.create(book);
            request.getRequestDispatcher("view/listofbooks.jsp").forward(request, response);
        }
        catch (FileNotFoundException e) {
            writer.println("You either did not specify a file to upload or are "
                    + "trying to upload a file to a protected or nonexistent "
                    + "location.");
            writer.println("<br/> ERROR: " + e.getMessage());
        }
        catch (IllegalImageResolution e) {
            writer.println("you pointed an image with wrong resolution");
            writer.println("<br/> ERROR: " + e.getMessage());
        }
        catch (IllegalBookCoverFileExtension e) {
            writer.println("wrong image extension");
            writer.println("<br/> ERROR: " + e.getMessage());
        }
        catch (IllegalBookFileExtension e) {
            writer.println("such book format doesn't supported");
            writer.println("<br/> ERROR: " + e.getMessage());
        }
        catch (RollbackException e) {
            writer.println("duplicate ISBN");
        }
        finally {
            if (writer != null) {
                writer.close();
            }
        }

    }

    private String getFileName(final Part part) {
        String partHeader = part.getHeader("content-disposition");
        for (String content : partHeader.split(";")) {
            if (content.trim().startsWith("filename")) {
                return content.substring(content.indexOf("=") + 1).trim().replace("\"", "");
            }
        }
        return null;
    }

    private String getISBN(Part part) {
        String partHeader = part.getHeader("content-disposition");
        for (String content : partHeader.split(";")) {
            if (content.trim().startsWith("filename")) {
                return content.substring(content.indexOf("=") + 1).trim().replace("\"", "");
            }
        }
        return null;

    }

//    private File createBookDirectoryStructure(Part part) {
//        String bookFileName = getFileName(part);
//        final String allBooksRoot = File.separator + "Temp" + File.separator + "Test";
//        String bookDirectoryName = bookFileName.substring(0, bookFileName.lastIndexOf("."));
//        File bookDirectory = new File(allBooksRoot + File.separator + bookDirectoryName) ;
//        bookDirectory.mkdirs();
//        return bookDirectory;
//    }

    private File generateBookDirectoryStructure(String bookDirectoryName) {
        final String allBooksRoot = File.separator + "Temp" + File.separator + "Test";
        File bookDirectory = new File(allBooksRoot + File.separator + bookDirectoryName);
        bookDirectory.mkdirs();
        return bookDirectory;

    }

    private String getFileExtension(String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
        return extension;
    }

    private Map<String, String> process(HttpServletRequest request) throws
            ServletException, IOException, IllegalArgumentException {
//            ServletException, IOException, IllegalImageResolution, IllegalBookCoverFileExtension, IllegalBookFileExtension {

        Map<String, String> pathFiles = new HashMap<>();
        BookParameters parameters = BookParameters.getInstance();
        OutputStream outputStream = null;
        InputStream inputStream = null;
        Part bookPart = request.getPart("bookFile");
        Part coverPart = request.getPart("coverFile");
        String fileBookName = getFileName(bookPart);
        String fileCoverName = getFileName(coverPart);
        File bookDirectory = null;
        String pathToFile = null;






        try {
            boolean isBookExtensionProper = parameters.checkBookExtension(getFileExtension(fileBookName));
            boolean isCoverExtensionProper = parameters.checkBookCoverExtension(getFileExtension(fileCoverName));

            if (!isBookExtensionProper || !isCoverExtensionProper) {
                throw new FileNotFoundException();
            }

            inputStream = coverPart.getInputStream();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int read;
            byte[] readBytes = new byte[1024];
            while ((read = inputStream.read(readBytes)) != -1) {
                byteArrayOutputStream.write(readBytes);
            }
            byte[] imageBytes = byteArrayOutputStream.toByteArray();
            boolean isCoverResolutionProper = parameters.checkCoverResolution(imageBytes);
            if (!isCoverResolutionProper) {
                throw new IllegalImageResolution("wrong resolution");
            }

            bookDirectory = generateBookDirectoryStructure(request.getParameter("isbn"));

            inputStream = bookPart.getInputStream();

            pathToFile = bookDirectory.getCanonicalPath() + File.separator + fileBookName;
            outputStream = new FileOutputStream(new File(pathToFile));
            readBytes = new byte[1024];
            while ((read = inputStream.read(readBytes)) != -1) {
                outputStream.write(readBytes, 0, read);
            }
            pathFiles.put("bookFile", pathToFile);

            pathToFile = bookDirectory.getCanonicalPath() + File.separator + fileCoverName;
            outputStream = new FileOutputStream(new File(pathToFile));
            outputStream.write(imageBytes);
            pathFiles.put("coverFile", pathToFile);
            return pathFiles;

        }
        finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }

    }
}
